"""
Similar to syntax_color.py but this is intended more for being able to
copy+paste actual code into your Django templates without needing to
escape or anything crazy.

Example:

 {% load highlighting %}

 <style>
 .highlight { background: #f8f8f8; }
 .highlight { font-size: 11px; margin: 1em; border: 1px solid #ccc;
              border-left: 3px solid #F90; padding: 0; }
 .highlight pre { padding: 1em; overflow: auto; line-height: 120%; margin: 0; }
 .predesc { margin: 1.5em 1.5em -2.5em 1em; text-align: right;
            font: bold 12px Tahoma, Arial, sans-serif;
            letter-spacing: 1px; color: #333; }
 </style>

 <h2>check out this code</h2>

 {% highlight 'python' 'Excerpt: blah.py' %}
 def need_food(self):
     print("Love is <colder> than &death&")
 {% endhighlight %}
"""

from django import template
from django.template import (
    Context,
    Node,
    Template,
    TemplateSyntaxError,
    Variable,
)
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe

try:
    from pygments import highlight as pyghighlight
    from pygments.lexers import get_lexer_by_name
    from pygments.formatters import HtmlFormatter

    HAS_PYGMENTS = True
except ImportError:  # pragma: no cover
    HAS_PYGMENTS = False

register = template.Library()


@register.filter(is_safe=True)
@stringfilter
def parse_template(value):
    return mark_safe(Template(value).render(Context()))


class CodeNode(Node):
    def __init__(self, language, nodelist, name=""):
        self.language = Variable(language)
        self.nodelist = nodelist
        if name:
            self.name = Variable(name)
        else:
            self.name = None

    def render(self, context):
        code = self.nodelist.render(context).strip()
        lexer = get_lexer_by_name(self.language.resolve(context))
        formatter = HtmlFormatter(linenos=False)
        html = ""
        if self.name:
            name = self.name.resolve(context)
            html = '<div class="predesc"><span>%s</span></div>' % name
        return html + pyghighlight(code, lexer, formatter)


@register.tag
def highlight(parser, token):
    """
    Tag to put a highlighted source code <pre> block in your code.
    This takes two arguments, the language and a little explaination message
    that will be generated before the code.  The second argument is optional.

    Your code will be fed through pygments so you can use any language it
    supports.

    Usage::

      {% load highlighting %}
      {% highlight 'python' 'Excerpt: blah.py' %}
      def need_food(self):
          print("Love is colder than death")
      {% endhighlight %}

    """
    if not HAS_PYGMENTS:  # pragma: no cover
        raise ImportError("Please install 'pygments' library to use highlighting.")
    nodelist = parser.parse(("endhighlight",))
    parser.delete_first_token()
    bits = token.split_contents()[1:]
    if len(bits) < 1:
        raise TemplateSyntaxError("'highlight' statement requires an argument")
    return CodeNode(bits[0], nodelist, *bits[1:])
